#include "ms618_algbase.h"

using namespace MeasurE618;
once_flag AlgBase::m_flag;
std::vector< std::shared_ptr<std::condition_variable>> AlgBase::cvarptrVec;
std::vector < std::shared_ptr<std::mutex>  > AlgBase::mtxptrVec;
std::vector <bool> AlgBase::flagVec;
std::vector< std::shared_ptr<std::condition_variable>> AlgBase::cvarptrfrontVec;
std::vector < std::shared_ptr<std::mutex>  > AlgBase::mtxptrfrontVec;
std::vector <bool> AlgBase::flagfrontVec;
std::vector< std::shared_ptr<std::condition_variable>> AlgBase::cvarptrsideVec;
std::vector < std::shared_ptr<std::mutex>  > AlgBase::mtxptrsideVec;
std::vector <bool> AlgBase::flagsideVec;
std::vector<std::vector<Point2f>> AlgBase::datumBackVec;
std::vector<std::vector<Point2f>> AlgBase::datumFrontVec;
std::vector<std::vector<Point2f>> AlgBase::datumSideVec;
std::vector <ParameterClass> AlgBase::m_dataAllVec;

once_flag               AlgBase::m_setStandardValOnceFlag         ;
std::string             AlgBase::m_dir_edge_extraction_parameters ;
std::string             AlgBase::m_dir_template_classifier_model  ;
std::string             AlgBase::m_dir_template_feature_model     ;
std::string             AlgBase::m_dir_template_images            ;
std::map<string, float> AlgBase::m_standardValMap                 ;
string                  AlgBase::m_dir_distance_fitting_model     ;
std::map<std::string, std::vector<float>> AlgBase::m_phypixpara  ;
bool                    AlgBase::m_isSetWorkpieceInfo = false     ;
bool                    AlgBase::m_isLoadXml          = false     ;
string                  AlgBase::m_modeName                       ;
string                  AlgBase::m_xmlFileNamePre                    ;

AlgBase::AlgBase(int n)
{
    std::call_once(m_flag, InitFunAll, n);

    if(!m_isLoadXml) {
        if(!LoadFitPara()) {
            qCritical() << "量测算法：E618加载参数失败";
            return;
        }
        m_isLoadXml = true;
    }
}

AlgBase::~AlgBase()
{
    if(m_isSetWorkpieceInfo) {
        m_isSetWorkpieceInfo = false;
    }

    if(m_isLoadXml) {
        m_isLoadXml = false;
    }
}

void AlgBase::setNumberOfAlg(const int n)
{
    datumBackVec.resize(n);
    datumFrontVec.resize(n);
    datumSideVec.resize(n);
    AlgBase::cvarptrVec.resize(n);
    AlgBase::mtxptrVec.resize(n);
    AlgBase::flagVec.resize(n);
    AlgBase::cvarptrfrontVec.resize(n);
    AlgBase::mtxptrfrontVec.resize(n);
    AlgBase::flagfrontVec.resize(n);
    AlgBase::cvarptrsideVec.resize(n);
    AlgBase::mtxptrsideVec.resize(n);
    AlgBase::flagsideVec.resize(n);

    for (size_t i = 0; i < AlgBase::flagVec.size(); i++)
    {
        AlgBase::flagVec[i] = false;
        std::shared_ptr<std::condition_variable> cvar(new std::condition_variable());
        std::shared_ptr<std::mutex> mtx(new std::mutex());
        cvarptrVec[i]=cvar;
        mtxptrVec[i] = mtx;

        AlgBase::flagfrontVec[i] = false;
        std::shared_ptr<std::condition_variable> cvarfront(new std::condition_variable());
        std::shared_ptr<std::mutex> mtxfront(new std::mutex());
        cvarptrfrontVec[i] = cvarfront;
        mtxptrfrontVec[i] = mtxfront;

        AlgBase::flagsideVec[i] = false;
        std::shared_ptr<std::condition_variable> cvarside(new std::condition_variable());
        std::shared_ptr<std::mutex> mtxside(new std::mutex());
        cvarptrsideVec[i] = cvarside;
        mtxptrsideVec[i] = mtxside;
    }

}

void AlgBase::InitFunAll(const int n)
{
    setNumberOfAlg(n);

    {
        //back circle L12345678-> 01234567
        std::vector<int> toll{0,1,2,3,4,5,6,7};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem+1));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("L")+std::to_string((elem+1))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("L.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });

    }

    {
        //back circle RC-> 8
        int regionNum=8;
        std::string  backxml("back.xml");
        cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
        std::string tagname=std::string("temp_info")+std::to_string(20);
        cv::Rect regionRect;
        fs[tagname][std::string("match_region")]>>regionRect;
        fs.release();
        std::string  backImg("back/"),backImgTmp("/best_temp.png");
        std::vector<cv::Mat> imgVec;

        std::string imgname=m_dir_template_images+backImg+std::string("RC")+backImgTmp;
        cv::Mat img=cv::imread(imgname.c_str(),0);
        imgVec.push_back(img.clone());

        cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("RC.xml")).c_str(),cv::FileStorage::READ);
        ParameterClass obj;
        obj.m_regionNum=regionNum;
        obj.m_templateImageVec=imgVec;
        obj.m_regionRect=regionRect;
        fse["voc"]>>obj.m_edgeParam;
        fse.release();
        m_dataAllVec.push_back(obj);
    }

    {
        //back circle D12345678-> 9 10 11 12 13 14 15 16
        std::vector<int> toll{9, 10, 11, 12, 13, 14, 15, 16};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("D")+std::to_string((elem-8))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("D.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });

    }

    {
        //back  SE123-> 17 18 19
        std::vector<int> toll{17, 18, 19};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string((elem-16))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SE.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });

    }

    {
        //back  SS123456-> 20 21 22 23 24 25
        std::vector<int> toll{20, 21, 22, 23 ,24 ,25};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem+1));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("SS")+std::to_string((elem-19))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SS.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });

    }

    {
        //back  Setup1-> 26
        std::vector<int> toll{26};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("back.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem+1));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("back/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("SetUp1")+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SE.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });

    }


    {
        //front SE12345-> 27,28,29,30,31
        std::vector<int> toll{27,28,29,30,31};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("front.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem-26));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("front/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string((elem-26))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SE.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });
    }

    {
        //high  SE3,SE6-> 32,33
        std::vector<int> toll{ 32,33};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  backxml("high.xml");
            cv::FileStorage fs((m_dir_template_images+backxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem-31));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("high/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname;
            if(elem==32)
            imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string((elem-29))+backImgTmp;
            else
            imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string((elem-27))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SE.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });
    }

    {
        //side SE7->34
        std::vector<int> toll{34};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  frontxml("side.xml");
            cv::FileStorage fs((m_dir_template_images+frontxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem-33));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("side/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname=m_dir_template_images+backImg+std::string("SE")+std::to_string((elem-27))+backImgTmp;
            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());
            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SE.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);

        });
    }

    {
      //side1 SetUp4-x -> 35,SetUp4-y -> 36
        std::vector<int> toll{35,36};
        for_each(toll.begin(),toll.end(),[](int &elem){
            int regionNum=elem;
            std::string  frontxml("side1.xml");
            cv::FileStorage fs((m_dir_template_images+frontxml).c_str(),cv::FileStorage::READ);
            std::string tagname=std::string("temp_info")+std::to_string((elem-34));
            cv::Rect regionRect;
            fs[tagname][std::string("match_region")]>>regionRect;
            fs.release();
            std::string  backImg("side1/"),backImgTmp("/best_temp.png");
            std::vector<cv::Mat> imgVec;
            std::string imgname;
            if(elem==35)
            imgname=m_dir_template_images+backImg+std::string("SetUp4-x")+backImgTmp;
            else
            imgname=m_dir_template_images+backImg+std::string("SetUp4-y")+backImgTmp;

            cv::Mat img=cv::imread(imgname.c_str(),0);
            imgVec.push_back(img.clone());

            cv::FileStorage fse((m_dir_edge_extraction_parameters+backImg+std::string("SE.xml")).c_str(),cv::FileStorage::READ);
            ParameterClass obj;
            obj.m_regionNum=regionNum;
            obj.m_templateImageVec=imgVec;
            obj.m_regionRect=regionRect;
            fse["voc"]>>obj.m_edgeParam;
            fse.release();
            m_dataAllVec.push_back(obj);
        });
    }
}
bool AlgBase::InitPath(const string &path)
{
    m_dir_edge_extraction_parameters = (path + "/E618/MeasureData618/edge_extraction_parameters/");
    m_dir_template_classifier_model  = (path + "/E618/MeasureData618/template_classifier_model/") ;
    m_dir_template_feature_model     = (path + "/E618/MeasureData618/template_feature_model/");
    m_dir_template_images            = (path + "/E618/MeasureData618/template_images/");
    m_dir_distance_fitting_model     = (path + "/E618/MeasureData618/distance_fitting_model/");

    qDebug() << "init path: " << QString::fromStdString(m_dir_distance_fitting_model);

    auto isDirExist = [](const std::string &dirName) {
        QDir dir(QString::fromStdString(dirName));
        if (!dir.exists()) {
            qCritical() << QString("灰度算法：量测算法E618配置文件路径不存在：%1").arg(QString::fromStdString(dirName));
            return false;
        } else {
            return true;
        }
    };

    if (!isDirExist(m_dir_edge_extraction_parameters)
            || !isDirExist(m_dir_template_classifier_model)
            || !isDirExist(m_dir_template_feature_model)
            || !isDirExist(m_dir_template_images)
            || !isDirExist(m_dir_distance_fitting_model))
    {
        return false;
    }
    qDebug() << "init path success " ;
    return true;
}

bool AlgBase::SetTemplatePath(const string &path)
{
    static bool called      = false;
    static bool initResult  = false;
    if(!called) {
        initResult = InitPath(path);
        called = true;
    }
    return initResult;
}

void AlgBase::SetStandardVal(const std::map<string, float> standardVal)
{
    std::call_once(m_setStandardValOnceFlag, InitStandardVal, standardVal);
}

void AlgBase::SetWorkpieceInfo(const string &modeName, const string &workpieceType)
{
    if(!m_isSetWorkpieceInfo) {
        m_modeName = modeName;
        m_xmlFileNamePre = ("fitpara_" + modeName + "_" + workpieceType + "_");
        std::string xmlfileName = m_xmlFileNamePre;
        m_isSetWorkpieceInfo = true;
    }
}

bool AlgBase::LoadFitPara()
{
    qDebug() << "load fit para start";
    {
        // list all xml files
        vector<string> pyhpixstr = LoadFiles(QString::fromStdString(m_dir_distance_fitting_model), "*.xml");
        std::vector<std::string> faiItemList = {
            "FAI11-SS1-X-distance",
            "FAI14-SE1-Y-distance",
            "FAI20-RC-X1-distance",
            "FAI20-RC-X2-distance",
            "FAI22-SS1-position",
            "FAI22-SS1-X-distance",
            "FAI22-SS1-Y-distance",
            "FAI22-SS2-position",
            "FAI22-SS2-X-distance",
            "FAI22-SS2-Y-distance",
            "FAI22-SS3-position",
            "FAI22-SS3-X-distance",
            "FAI22-SS3-Y-distance",
            "FAI22-SS4-position",
            "FAI22-SS4-X-distance",
            "FAI22-SS4-Y-distance",
            "FAI22-SS5-position",
            "FAI22-SS5-X-distance",
            "FAI22-SS5-Y-distance",
            "FAI22-SS6-position",
            "FAI22-SS6-X-distance",
            "FAI22-SS6-Y-distance",
            "FAI3-SE3-Y-distance",
            "FAI36-SE7-Y1-distance",
            "FAI36-SE7-Y2-distance",
            "FAI36-SE7-Y3-distance",
            "FAI37-SE7-Y1-distance",
            "FAI37-SE7-Y2-distance",
            "FAI37-SE7-Y3-distance",
            "FAI37-SE7-Y4-distance",
            "FAI38-SE7-Y1-distance",
            "FAI38-SE7-Y2-distance",
            "FAI38-SE7-Y3-distance",
            "FAI38-SE7-Y4-distance",
            "FAI44-SE1-Y1-distance",
            "FAI44-SE1-Y2-distance",
            "FAI47-SE2-X-distance",
            "FAI48-SE2-X-distance",
            "FAI49-SE5-Y-distance",
            "FAI5-SE3-Y-distance",
            "FAI66-SE3-Y1-distance",
            "FAI66-SE3-Y2-distance",
            "FAI68-RC-Y1-distance",
            "FAI68-RC-Y2-distance",
            "FAI68-RC-Y3-distance",
            "FAI68-RC-Y4-distance",
            "FAI69-RC-X-distance",
            "FAI69-RC-X-position",
            "FAI7-SE2-X-distance",
            "FAI70-RC-Y-distance",
            "FAI70-RC-Y-position",
            "FAI72-SE4-X-distance",
            "FAI8-SE2-X-distance",
            "FAI9-SE2-X-distance",
            "FAI91-SS1-diam",
            "FAI91-SS2-diam",
            "FAI91-SS3-diam",
            "FAI91-SS4-diam",
            "FAI91-SS5-diam",
            "FAI91-SS6-diam",
            "FAI73-D-diam",
            "FAI74-D-position",
            "FAI74-D-X-distance",
            "FAI74-D-Y-distance",
            "FAI75-L-diam",
            "FAI76-L-position",
            "FAI76-L-X-distance",
            "FAI76-L-Y-distance"
        };

        auto LoadFitPara_ = [&](const FileStorage& fs,
                const std::string &prefix,
                const std::string &name,
                std::map<std::string, std::vector<float>>& phypixpara)
        {
            for(size_t i = 0; i < 3; i++)
            {
                phypixpara[prefix + std::string(name)].push_back(static_cast<float>(fs[std::string(name)][i]));
            }
        };

        for(size_t i = 0; i < pyhpixstr.size(); i++) {
            FileStorage fs((m_dir_distance_fitting_model + pyhpixstr[i]).c_str(),FileStorage::READ);
            std::string faiPre;
            size_t found = pyhpixstr[i].find(".xml");

            faiPre = (pyhpixstr[i].substr(0, found) + "_");

            for(auto &item : faiItemList) {
                LoadFitPara_(fs, faiPre, item, m_phypixpara);
            }
            fs.release();
        }
    }

    return true;
}

vector<std::string> AlgBase::LoadFiles(const QString &path, QString ext)
{
    QDir dir(path);
    QStringList nameFilters;
    nameFilters << ext;
    QStringList files = dir.entryList(nameFilters, QDir::Files | QDir::Readable, QDir::Name);

    vector<std::string> fileList;
    for(auto &file : files) {
        fileList.push_back(file.toStdString());
    }

    return fileList;
}

void AlgBase::InitStandardVal(const std::map<string, float> standardVal)
{
    for (auto &iter : standardVal) {
        m_standardValMap[iter.first] = iter.second;
    }
}

float AlgBase::CalcMeasureDistance(const vector<float> &coefficient, float measureItem)
{
    if(coefficient.empty()) {
        qCritical() << "empty coefficient";
        Q_ASSERT(coefficient.size() != 0);
        return -1;
    }

    return coefficient[0]*measureItem*measureItem + coefficient[1]*measureItem + coefficient[2];
}

float AlgBase::CalcPixelAccordExpectDist(const vector<float> &coefficient,
                                                   float expectDist)
{
    if(coefficient.empty()) {
        qCritical() << "empty coefficient";
        Q_ASSERT(coefficient.size() != 0);
        return -1;
    }

    float ret = 0.0f;
    if(0 != coefficient[1]) {
        ret = (expectDist - coefficient[2])/coefficient[1];
    }
    return ret;
}

void AlgBase::TemplateMatch(cv::Mat &img,ParameterClass &obj,std::vector<cv::Rect> &rangVec)
{

        cv::Mat templ=obj.m_templateImageVec[0];
        int result_cols =  img.cols - templ.cols + 1;
        int result_rows = img.rows - templ.rows + 1;
        cv::Mat result;

        result.create( result_cols, result_rows, CV_32FC1 );
//        qDebug() << QString("result.create( %1, %2, CV_32FC1 )").arg(result_cols).arg(result_rows);
//        qDebug() << QString("obj.m_regionRect: x=%1, y=%2, w=%3, h=%4")
//                    .arg(obj.m_regionRect.x).arg(obj.m_regionRect.y)
//                    .arg(obj.m_regionRect.width).arg(obj.m_regionRect.height);

//        qDebug() << QString("img: rows=%1, cols=%2").arg(img.rows).arg(img.cols);
        cv::Mat imgRoi=img(obj.m_regionRect);
//        qDebug() << QString("img(obj.m_regionRect)");
        matchTemplate( imgRoi, templ, result,  CV_TM_CCOEFF_NORMED );
//        qDebug() << QString("matchTemplate( imgRoi, templ, result,  CV_TM_CCOEFF_NORMED )");
        normalize( result, result, 0, 1, NORM_MINMAX, -1, cv::Mat() );
//        qDebug() << QString("normalize( result, result, 0, 1, NORM_MINMAX, -1, cv::Mat() )");
        double minVal; double maxVal; cv::Point minLoc; cv::Point maxLoc;
        cv::Point matchLoc;
        minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() );
        matchLoc.x=maxLoc.x+obj.m_regionRect.x;
        matchLoc.y=maxLoc.y+obj.m_regionRect.y;
        cv::Rect rz;
        rz.x=matchLoc.x,rz.y=matchLoc.y,rz.width=templ.cols,rz.height=templ.rows;
        rangVec.push_back(rz);
}

void AlgBase::CoordinateTransformation(std::vector<cv::Point2f> &ptsVec, cv::Point2f &ptsIn,cv::Point2f &ptsOut)
{
    float A1=0.0,B1=0.0,C1=0.0;
    float A2=0.0,B2=0.0,C2=0.0;
    A1=ptsVec[1].y-ptsVec[0].y;
    B1=ptsVec[0].x-ptsVec[1].x;
    C1=ptsVec[0].y*ptsVec[1].x-ptsVec[0].x*ptsVec[1].y;
    ptsOut.y=abs(A1*ptsIn.x+B1*ptsIn.y+C1)/sqrt(A1*A1+B1*B1);

    A2=ptsVec[2].y-ptsVec[0].y;
    B2=ptsVec[0].x-ptsVec[2].x;
    C2=ptsVec[0].y*ptsVec[2].x-ptsVec[0].x*ptsVec[2].y;
    ptsOut.x=abs(A2*ptsIn.x+B2*ptsIn.y+C2)/sqrt(A2*A2+B2*B2);

}

void AlgBase::CoordinateTransformationRelateToDot(const std::vector<Point2f> &ptsVec,
                                                  const Point2f &ptsIn,
                                                  Point2f &ptsOut)
{
    ptsOut.x = ptsIn.x - ptsVec[0].x;
    ptsOut.y = ptsIn.y - ptsVec[0].y;
}

void AlgBase::clearAllflag(int i)
{
//    for (size_t i = 0; i < AlgBase::flagVec.size(); i++)
//    {
        AlgBase::flagVec[i] = false;
        AlgBase::flagfrontVec[i] = false;
        AlgBase::flagsideVec[i] = false;
        //    }
}

float AlgBase::CalcPosition(const string &measureItemX,
                            const string &measureItemY,
                            const string &measureItemPos,
                            const std::string &prefix,
                            edgedetect &obj,
                            float expectRealDistX,
                            float expectRealDistY,
                            float predictPixelX,
                            float predictPixelY,
                            std::map<string, float> &measRes)
{
    if(measureItemX.empty() ||
       measureItemY.empty() ||
       measureItemPos.empty())
    {
        Q_ASSERT(measureItemX.empty());
        qCritical() << "cv_measure_618 input empty measure item";
        return -1;
    }

    float faiPosPixelX = CalcPixelAccordExpectDist(m_phypixpara[measureItemX],
            expectRealDistX);
    float faiPosPixelY = CalcPixelAccordExpectDist(m_phypixpara[measureItemY],
            expectRealDistY);
    double faiPosPixel = obj.GetPosition(cv::Point2f(predictPixelX, predictPixelY),
                                         cv::Point2f(faiPosPixelX, faiPosPixelY)
                                        );
    std::string measureItemPosPixel = measureItemPos + "_pixel";
    std::string measureItemPosReal  = measureItemPos + "_real";
    measRes.insert(std::make_pair(string(measureItemPosPixel), faiPosPixel));
    float faiPosDis = CalcMeasureDistance(m_phypixpara[prefix + std::string(measureItemPos)], faiPosPixel);
    measRes.insert(std::make_pair(string(measureItemPosReal), faiPosDis));
}

//void AlgBb vase::TemplateMatch(cv::Mat &img, int &&num, std::vector<Rect> &rangVec)
//{

// rangVec.resize(num.m_templateImageVec.size());
//#pragma omp parallel for num_threads(6)
//    for(int i=0;i<int(num.m_templateImageVec.size());i++)
//    {
//        cv::Mat templ=num.m_templateImageVec[i];
//        int result_cols =  img.cols - templ.cols + 1;
//        int result_rows = img.rows - templ.rows + 1;
//        cv::Mat result;
//        result.create( result_cols, result_rows, CV_32FC1 );
//        cv::Mat imgRoi=img(num.m_regionRect);
//        matchTemplate( imgRoi, templ, result,  CV_TM_CCOEFF_NORMED );
//        normalize( result, result, 0, 1, NORM_MINMAX, -1, cv::Mat() );
//        double minVal; double maxVal; cv::Point minLoc; cv::Point maxLoc;
//        cv::Point matchLoc;
//        minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() );
//        matchLoc=maxLoc;
//        cv::Rect rz;
//        rz.x=matchLoc.x,rz.y=matchLoc.y,rz.width=templ.cols,rz.height=templ.rows;
//        rangVec.push_back(rz);
//    }

//}

